﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using IntegratedMeasuring.Pages;

namespace IntegratedMeasuring.Utils;

public class DongleHandler : IDisposable
{
    private IntPtr _hwnd = IntPtr.Zero;
    private IntPtr _notifyHandle = IntPtr.Zero;
    private TW_SoftKey _softKey = new TW_SoftKey();

    private string _devicePath;

    // 设备接口类 GUID（USB 设备）
    private static readonly Guid GUID_DEVINTERFACE_USB_DEVICE = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED");
    private const int WM_DEVICECHANGE = 0x0219;
    private const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
    private const int DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000;
    private const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005;

    [StructLayout(LayoutKind.Sequential)]
    private struct DEV_BROADCAST_DEVICEINTERFACE
    {
        public int dbcc_size;
        public int dbcc_devicetype;
        public int dbcc_reserved;
        public Guid dbcc_classguid;
        public short dbcc_name;
    }

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, int Flags);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool UnregisterDeviceNotification(IntPtr Handle);
    
    private void RegisterDeviceNotification()
    {
        var dbi = new DEV_BROADCAST_DEVICEINTERFACE
        {
            dbcc_size = Marshal.SizeOf(typeof(DEV_BROADCAST_DEVICEINTERFACE)),
            dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE,
            dbcc_reserved = 0,
            dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE,
            dbcc_name = 0
        };

        IntPtr buffer = Marshal.AllocHGlobal(dbi.dbcc_size);
        Marshal.StructureToPtr(dbi, buffer, true);

        _notifyHandle = RegisterDeviceNotification(_hwnd, buffer, DEVICE_NOTIFY_WINDOW_HANDLE);

        Marshal.FreeHGlobal(buffer);
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_DEVICECHANGE)
        {
            if (wParam is Win32.DBT_DEVICEREMOVECOMPLETE)
            {
                var ret = _softKey.FindPort(0, ref _devicePath);
                if (ret != 0)
                {
                    // 注意：这里无法使用async，因为WndProc不能是async
                    var confirmDialog = new ConfirmDialog("加密狗已拔出,软件即将关闭！");
                    confirmDialog.Show();
                    // 关闭软件
                    Environment.Exit(0);
                }
            }
        }
        return IntPtr.Zero;
    }
    
    public DongleHandler(Window window)
    {
        // 获取窗口句柄
        _hwnd = window.TryGetPlatformHandle()?.Handle ?? IntPtr.Zero;
        
        RegisterDeviceNotification();
    }
    
    public void Dispose()
    {
        if (_notifyHandle != IntPtr.Zero)
        {
            UnregisterDeviceNotification(_notifyHandle);
            _notifyHandle = IntPtr.Zero;
        }
    }

    public async Task<bool> CheckDongleAsync(Window parentWindow)
    {
        int ret = _softKey.FindPort(0, ref _devicePath);
        if (ret != 0)
        {
            var confirmDialog = new ConfirmDialog("未找到加密锁，请插入锁后再进行操作！");
            await confirmDialog.ShowDialog<bool?>(parentWindow);
            return false;
        }
        else
        {
            string outString = "";
            // 唯一编码字段
            ret = _softKey.Read(ref outString, 0, 16, _devicePath);
            if (ret != 0)
            {
                var confirmDialog = new ConfirmDialog("加密锁唯一编码读取失败");
                await confirmDialog.ShowDialog<bool?>(parentWindow);
                return false;
            }
            
            // 使用类型字段
            ret = _softKey.Read(ref outString, 25, 1, _devicePath);
            if (ret != 0)
            {
                var confirmDialog = new ConfirmDialog("加密锁限制字段读取失败");
                await confirmDialog.ShowDialog<bool?>(parentWindow);
                return false;
            }
            else
            {
                if (outString == "1")
                {
                    ret = _softKey.Write("2", 25, _devicePath);
                    if (ret != 0)
                    {
                        var confirmDialog = new ConfirmDialog("加密锁限制字段写入失败");
                        await confirmDialog.ShowDialog<bool?>(parentWindow);
                        return false;
                    }
                }
                else if (outString == "2")
                {
                    // 调用系统时间篡改检测
                    if (!await CheckSystemTimeTamperAsync(parentWindow))
                    {
                        return false;
                    }
                    else
                    {
                        outString = "";
                        ret = _softKey.Read(ref outString, 50, 10, _devicePath);
                        if (ret != 0)
                        {
                            var confirmDialog = new ConfirmDialog("加密锁有效期读取失败");
                            await confirmDialog.ShowDialog<bool?>(parentWindow);
                            return false;
                        }
                        else
                        {
                            var dateDue = outString.ToDateTime();
                            if (DateTime.Now < dateDue)
                            {
                                var span = dateDue.Subtract(DateTime.Now);
                                var dayDiff = span.Days + 1;
                                if (dayDiff < 7)
                                {
                                    var confirmDialog = new ConfirmDialog($"本软件还剩 {dayDiff} 天试用期，为了不耽误贵司使用，请尽早联系供应商！");
                                    await confirmDialog.ShowDialog<bool?>(parentWindow);
                                }
                                return true;
                            }
                            else
                            {
                                var confirmDialog = new ConfirmDialog($"本软件试用期已结束，为了不耽误贵司使用，请尽早联系供应商！");
                                await confirmDialog.ShowDialog<bool?>(parentWindow);
                                return false;
                            }
                        }
                    }
                }
                else if (outString == "3")
                {
                    // 永久使用
                    return true;
                }
                else
                {
                    var confirmDialog = new ConfirmDialog("此加密狗与软件不匹配！未知的限制字段类型");
                    await confirmDialog.ShowDialog<bool?>(parentWindow);
                    return false;
                }
            }
        }
        return true;
    }

    // 保持原有的同步方法以兼容现有代码
    public bool CheckDongle()
    {
        // 注意：这个方法现在会立即返回，不会显示对话框
        // 建议使用CheckDongleAsync方法
        int ret = _softKey.FindPort(0, ref _devicePath);
        if (ret != 0)
        {
            return false;
        }
        else
        {
            string outString = "";
            // 唯一编码字段
            ret = _softKey.Read(ref outString, 0, 16, _devicePath);
            if (ret != 0)
            {
                return false;
            }
            
            // 使用类型字段
            ret = _softKey.Read(ref outString, 25, 1, _devicePath);
            if (ret != 0)
            {
                return false;
            }
            else
            {
                if (outString == "1")
                {
                    ret = _softKey.Write("2", 25, _devicePath);
                    if (ret != 0)
                    {
                        return false;
                    }
                }
                else if (outString == "2")
                {
                    // 调用系统时间篡改检测
                    if (!CheckSystemTimeTamper())
                    {
                        return false;
                    }
                    else
                    {
                        outString = "";
                        ret = _softKey.Read(ref outString, 50, 10, _devicePath);
                        if (ret != 0)
                        {
                            return false;
                        }
                        else
                        {
                            var dateDue = outString.ToDateTime();
                            if (DateTime.Now < dateDue)
                            {
                                var span = dateDue.Subtract(DateTime.Now);
                                var dayDiff = span.Days + 1;
                                if (dayDiff < 7)
                                {
                                    // 试用期警告，但不阻止使用
                                }
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                    }
                }
                else if (outString == "3")
                {
                    // 永久使用
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        return true;
    }

    private static async Task<bool> CheckSystemTimeTamperAsync(Window parentWindow)
    {
        string cachePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "runtimeCache.data");
        DateTime now = DateTime.Now;
        if (File.Exists(cachePath))
        {
            try
            {
                string cacheTimeStr = File.ReadAllText(cachePath).Trim();
                if (DateTime.TryParse(cacheTimeStr, out DateTime cacheTime))
                {
                    if (cacheTime > now)
                    {
                        var confirmDialog = new ConfirmDialog("检测到系统时间被回拨，软件将无法继续运行！");
                        await confirmDialog.ShowDialog<bool?>(parentWindow);
                        return false;
                    }
                }
                else
                {
                    var confirmDialog = new ConfirmDialog("无效的缓存数据");
                    await confirmDialog.ShowDialog<bool?>(parentWindow);
                    return false;
                }
            }
            catch
            {
                // 读取或解析异常，忽略，继续写入
            }
        }
        // 验证通过或文件不存在，写入当前时间
        try
        {
            File.WriteAllText(cachePath, now.ToString("yyyy-MM-dd HH:mm:ss"));
        }
        catch
        {
            // 写入异常可忽略
        }
        return true;
    }

    private static bool CheckSystemTimeTamper()
    {
        string cachePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "runtimeCache.data");
        DateTime now = DateTime.Now;
        if (File.Exists(cachePath))
        {
            try
            {
                string cacheTimeStr = File.ReadAllText(cachePath).Trim();
                if (DateTime.TryParse(cacheTimeStr, out DateTime cacheTime))
                {
                    if (cacheTime > now)
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                // 读取或解析异常，忽略，继续写入
            }
        }
        // 验证通过或文件不存在，写入当前时间
        try
        {
            File.WriteAllText(cachePath, now.ToString("yyyy-MM-dd HH:mm:ss"));
        }
        catch
        {
            // 写入异常可忽略
        }
        return true;
    }
}


//公共函数说明

//***查找加密锁 
//int FindPort(int start, ref string OutKeyPath);

//***获到锁的版本
//int NT_GetIDVersion(ref short version,  string KeyPath);

//获到锁的扩展版本
//int NT_GetIDVersionEx(ref short version,  string KeyPath);

//***获到锁的ID
//int GetID(ref int id_1, ref int id_2, string KeyPath);

//***从加密锁中读取一批字节
//int YReadEx(byte[] OutData, short Address, short mylen, string HKey, string LKey, string KeyPath);

//***从加密锁中读取一个字节数据，一般不使用
//int YRead(ref byte OutData, short Address,string HKey, string LKey, string KeyPath);

//***写一批字节到加密锁中
//int YWriteEx(byte[] InData, short Address, short mylen, string HKey, string LKey, string KeyPath);

//***写一个字节的数据到加密锁中，一般不使用
//int YWrite(byte InData, short Address, string HKey, string LKey, string KeyPath);

//***从加密锁中读字符串
//int YReadString(ref string outstring, short Address, short mylen, string HKey, string LKey, string KeyPath);

//***写字符串到加密锁中
//int YWriteString(string InString, short Address, string HKey, string LKey, string KeyPath);


//***设置写密码
//int SetWritePassword(string W_HKey, string W_LKey, string new_HKey, string new_LKey, string KeyPath);

//***设置读密码
//int SetReadPassword(string W_HKey, string W_LKey, string new_HKey, string new_LKey, string KeyPath);

//'设置增强算法密钥一
//int SetCal_2(string Key , string KeyPath);

//使用增强算法一对字符串进行加密
//int EncString(string InString , ref string outstring , string KeyPath);

//使用增强算法一对二进制数据进行加密
// int Cal(byte[] InBuf, byte[] OutBuf, string KeyPath);


//***初始化加密锁函数
//int ReSet( string Path);

//***获取字符串长度
//int lstrlenA(string InString );

/// <summary>
/// 天威加密狗
/// </summary>
public class TW_SoftKey
{
    //private readonly string OriginWritePasswordH = "FFFFFFFF";
    //private readonly string OriginWritePasswordL = "FFFFFFFF";
    //private readonly string OriginReadPasswordH = "FFFFFFFF";
    //private readonly string OriginReadPasswordL = "FFFFFFFF";
    private readonly string OriginWritePasswordH = "00000000";
    private readonly string OriginWritePasswordL = "00000000";
    private readonly string OriginReadPasswordH = "00000000";
    private readonly string OriginReadPasswordL = "00000000";
    private readonly string AdvancedKey = "CA7DA7CFA951A1493845DA97DC391325";
    private readonly string WritePasswordH = "889535E2";
    private readonly string WritePasswordL = "27896E30";
    private readonly string ReadPasswordH = "E39AD0E7";
    private readonly string ReadPasswordL = "C28EC935";
    //private readonly string KEY = "FT58ATE5SS2021FF";
    public static readonly string EncryptResult = "0B2A7DDBAAA252A326472D1ACCB3F60900";


    private const ushort VID = 0x3689;
    private const ushort PID = 0x8762;
    private const ushort PID_NEW = 0X2020;
    private const ushort VID_NEW = 0X3689;
    private const ushort PID_NEW_2 = 0X2020;
    private const ushort VID_NEW_2 = 0X2020;
    private const short DIGCF_PRESENT = 0x2;
    private const short DIGCF_DEVICEINTERFACE = 0x10;
    private const short INVALID_HANDLE_VALUE = (-1);
    private const short ERROR_NO_MORE_ITEMS = 259;

    private const uint GENERIC_READ = 0x80000000;
    private const int GENERIC_WRITE = 0x40000000;
    private const uint FILE_SHARE_READ = 0x1;
    private const uint FILE_SHARE_WRITE = 0x2;
    private const uint OPEN_EXISTING = 3;
    private const uint FILE_ATTRIBUTE_NORMAL = 0x80;
    private const uint INFINITE = 0xFFFF;

    private const short MAX_LEN = 495;

    public const int FAILEDGENKEYPAIR = -21;
    public const int FAILENC = -22;
    public const int FAILDEC = -23;
    public const int FAILPINPWD = -24;
    public const int USBStatusFail = -50;  //USB操作失败，可能是没有找到相关的指令

    public const int SM2_ADDBYTE = 97;//加密后的数据会增加的长度
    public const int MAX_ENCLEN = 128; //最大的加密长度分组
    public const int MAX_DECLEN = (MAX_ENCLEN + SM2_ADDBYTE); //最大的解密长度分组
    public const int SM2_USENAME_LEN = 80;// '最大的用户名长度


    public const int ECC_MAXLEN = 32;
    public const int PIN_LEN = 16;

    private const byte GETVERSION = 0x01;
    private const byte GETID = 0x02;
    private const byte GETVEREX = 0x05;
    private const byte CAL_TEA = 0x08;
    private const byte SET_TEAKEY = 0x09;
    private const byte READBYTE = 0x10;
    private const byte WRITEBYTE = 0x11;
    private const byte YTREADBUF = 0x12;
    private const byte YTWRITEBUF = 0x13;
    private const byte MYRESET = 0x20;
    private const byte YTREBOOT = 0x24;
    private const byte SET_ECC_PARA = 0x30;
    private const byte GET_ECC_PARA = 0x31;
    private const byte SET_ECC_KEY = 0x32;
    private const byte GET_ECC_KEY = 0x33;
    private const byte MYENC = 0x34;
    private const byte MYDEC = 0X35;
    private const byte SET_PIN = 0X36;
    private const byte GEN_KEYPAIR = 0x37;
    private const byte YTSIGN = 0x51;
    private const byte YTVERIFY = 0x52;
    private const byte GET_CHIPID = 0x53;
    private const byte YTSIGN_2 = 0x53;

    [DllImport("kernel32.dll")]
    public static extern int lstrlenA(string InString);
    [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
    public static extern void CopyStringToByte(byte[] pDest, string pSourceg, int ByteLenr);
    [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
    public static extern void CopyByteToString(StringBuilder pDest, byte[] pSource, int ByteLenr);
    [DllImport("HID.dll")]
    private static extern bool HidD_GetAttributes(IntPtr HidDeviceObject, ref HIDD_ATTRIBUTES Attributes);
    [DllImport("HID.dll")]
    private static extern int HidD_GetHidGuid(ref GUID HidGuid);
    [DllImport("HID.dll")]
    private static extern bool HidD_GetPreparsedData(IntPtr HidDeviceObject, ref IntPtr PreparsedData);
    [DllImport("HID.dll")]
    private static extern int HidP_GetCaps(IntPtr PreparsedData, ref HIDP_CAPS Capabilities);
    [DllImport("HID.dll")]
    private static extern bool HidD_FreePreparsedData(IntPtr PreparsedData);
    [DllImport("HID.dll")]
    private static extern bool HidD_SetFeature(IntPtr HidDeviceObject, byte[] ReportBuffer, int ReportBufferLength);
    [DllImport("HID.dll")]
    private static extern bool HidD_GetFeature(IntPtr HidDeviceObject, byte[] ReportBuffer, int ReportBufferLength);
    [DllImport("SetupApi.dll")]
    private static extern IntPtr SetupDiGetClassDevsA(ref GUID ClassGuid, int Enumerator, int hwndParent, int Flags);
    [DllImport("SetupApi.dll")]
    private static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
    [DllImport("SetupApi.dll")]
    private static extern bool SetupDiGetDeviceInterfaceDetailA(IntPtr DeviceInfoSet, ref SP_INTERFACE_DEVICE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, int DeviceInterfaceDetailDataSize, ref int RequiredSize, int DeviceInfoData);
    [DllImport("SetupApi.dll")]
    private static extern bool SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, int DeviceInfoData, ref GUID InterfaceClassGuid, int MemberIndex, ref SP_INTERFACE_DEVICE_DATA DeviceInterfaceData);
    [DllImport("kernel32.dll", EntryPoint = "CreateFileA")]
    private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, uint lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, uint hTemplateFile);
    [DllImport("kernel32.dll")]
    private static extern int CloseHandle(IntPtr hObject);
    [DllImport("kernel32.dll")]
    private static extern int GetLastError();
    [DllImport("kernel32.dll", EntryPoint = "CreateSemaphoreA")]
    private static extern IntPtr CreateSemaphore(int lpSemaphoreAttributes, int lInitialCount, int lMaximumCount, string lpName);
    [DllImport("kernel32.dll")]
    private static extern int WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
    [DllImport("kernel32.dll")]
    private static extern int ReleaseSemaphore(IntPtr hSemaphore, int lReleaseCount, int lpPreviousCount);



    /// <summary>
    /// 用于将字节数组转化为宽字符串
    /// </summary>
    /// <param name="buffer"></param>
    /// <returns></returns>
    private string ByteConvertString(byte[] buffer)
    {
        char[] null_string = { '\0', '\0' };
        Encoding encoding = Encoding.Default;
        return encoding.GetString(buffer).TrimEnd(null_string);
    }

    /// <summary>
    /// 将16进制字符串转化为无符号长整型
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    private uint HexToInt(string s)
    {
        string[] hexch = { "0", "1", "2", "3", "4", "5", "6", "7",
                                   "8", "9", "A", "B", "C", "D", "E", "F"};
        s = s.ToUpper();
        int i, j;
        int r, n, k;
        string ch;

        k = 1; r = 0;
        for (i = s.Length; i > 0; i--)
        {
            ch = s.Substring(i - 1, 1);
            n = 0;
            for (j = 0; j < 16; j++)
                if (ch == hexch[j])
                    n = j;
            r += (n * k);
            k *= 16;
        }
        return unchecked((uint)r);
    }

    /// <summary>
    /// 16进制字符串转化为字节数组
    /// </summary>
    /// <param name="InString"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    private int HexStringToByteArray(string InString, ref byte[] b)
    {
        int nlen;
        int retutn_len;
        int n, i;
        string temp;
        nlen = InString.Length;
        if (nlen < 16) retutn_len = 16;
        retutn_len = nlen / 2;
        b = new byte[retutn_len];
        i = 0;
        for (n = 0; n < nlen; n = n + 2)
        {
            temp = InString.Substring(n, 2);
            b[i] = (byte)HexToInt(temp);
            i = i + 1;
        }
        return retutn_len;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="inb"></param>
    /// <param name="outb"></param>
    /// <param name="Key"></param>
    public void EnCode(byte[] inb, byte[] outb, string Key)
    {

        UInt32 cnDelta, y, z, a, b, c, d, temp_2;
        UInt32[] buf = new UInt32[16];
        int n, i, nlen;
        UInt32 sum;
        //UInt32 temp, temp_1;
        string temp_string;


        cnDelta = 2654435769;
        sum = 0;

        nlen = Key.Length;
        i = 0;
        for (n = 1; n <= nlen; n = n + 2)
        {
            temp_string = Key.Substring(n - 1, 2);
            buf[i] = HexToInt(temp_string);
            i = i + 1;
        }
        a = 0; b = 0; c = 0; d = 0;
        for (n = 0; n <= 3; n++)
        {
            a = (buf[n] << (n * 8)) | a;
            b = (buf[n + 4] << (n * 8)) | b;
            c = (buf[n + 4 + 4] << (n * 8)) | c;
            d = (buf[n + 4 + 4 + 4] << (n * 8)) | d;
        }



        y = 0;
        z = 0;
        for (n = 0; n <= 3; n++)
        {
            temp_2 = inb[n];
            y = (temp_2 << (n * 8)) | y;
            temp_2 = inb[n + 4];
            z = (temp_2 << (n * 8)) | z;
        }


        n = 32;

        while (n > 0)
        {
            sum = cnDelta + sum;

            /*temp = (z << 4) & 0xFFFFFFFF;
            temp = (temp + a) & 0xFFFFFFFF;
            temp_1 = (z + sum) & 0xFFFFFFFF;
            temp = (temp ^ temp_1) & 0xFFFFFFFF;
            temp_1 = (z >> 5) & 0xFFFFFFFF;
            temp_1 = (temp_1 + b) & 0xFFFFFFFF;
            temp = (temp ^ temp_1) & 0xFFFFFFFF;
            temp = (temp + y) & 0xFFFFFFFF;
            y = temp & 0xFFFFFFFF;*/
            y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);

            /*temp = (y << 4) & 0xFFFFFFFF;
            temp = (temp + c) & 0xFFFFFFFF;
            temp_1 = (y + sum) & 0xFFFFFFFF;
            temp = (temp ^ temp_1) & 0xFFFFFFFF;
            temp_1 = (y >> 5) & 0xFFFFFFFF;
            temp_1 = (temp_1 + d) & 0xFFFFFFFF;
            temp = (temp ^ temp_1) & 0xFFFFFFFF;
            temp = (z + temp) & 0xFFFFFFFF;
            z = temp & 0xFFFFFFFF;*/
            z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
            n = n - 1;

        }

        for (n = 0; n <= 3; n++)
        {
            outb[n] = System.Convert.ToByte((y >> (n * 8)) & 255);
            outb[n + 4] = System.Convert.ToByte((z >> (n * 8)) & 255);
        }

    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="inb"></param>
    /// <param name="outb"></param>
    /// <param name="Key"></param>
    private void DeCode(byte[] inb, byte[] outb, string Key)
    {

        UInt32 cnDelta, y, z, a, b, c, d, temp_2;
        UInt32[] buf = new UInt32[16];
        int n, i, nlen;
        UInt32 sum;
        //UInt32 temp, temp_1;
        string temp_string;


        cnDelta = 2654435769;
        sum = 0xC6EF3720;

        nlen = Key.Length;
        i = 0;
        for (n = 1; n <= nlen; n = n + 2)
        {
            temp_string = Key.Substring(n - 1, 2);
            buf[i] = HexToInt(temp_string);
            i = i + 1;
        }
        a = 0; b = 0; c = 0; d = 0;
        for (n = 0; n <= 3; n++)
        {
            a = (buf[n] << (n * 8)) | a;
            b = (buf[n + 4] << (n * 8)) | b;
            c = (buf[n + 4 + 4] << (n * 8)) | c;
            d = (buf[n + 4 + 4 + 4] << (n * 8)) | d;
        }



        y = 0;
        z = 0;
        for (n = 0; n <= 3; n++)
        {
            temp_2 = inb[n];
            y = (temp_2 << (n * 8)) | y;
            temp_2 = inb[n + 4];
            z = (temp_2 << (n * 8)) | z;
        }


        n = 32;

        while (n-- > 0)
        {
            z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
            y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
            sum -= cnDelta;

        }

        for (n = 0; n <= 3; n++)
        {
            outb[n] = System.Convert.ToByte((y >> (n * 8)) & 255);
            outb[n + 4] = System.Convert.ToByte((z >> (n * 8)) & 255);
        }

    }

    /// <summary>
    /// 使用增强算法，加密字符串
    /// </summary>
    /// <param name="InString"></param>
    /// <param name="Key"></param>
    /// <returns></returns>
    private string EncryptString(string InString, string Key)
    {

        byte[] b, outb;
        byte[] temp = new byte[8], outtemp = new byte[8];
        int n, i, nlen, outlen;
        string outstring;


        nlen = lstrlenA(InString) + 1;
        if (nlen < 8)
            outlen = 8;
        else
            outlen = nlen;
        b = new byte[outlen];
        outb = new byte[outlen];

        CopyStringToByte(b, InString, nlen);

        b.CopyTo(outb, 0);

        for (n = 0; n <= outlen - 8; n = n + 8)
        {
            for (i = 0; i < 8; i++) temp[i] = b[i + n];
            EnCode(temp, outtemp, Key);
            for (i = 0; i < 8; i++) outb[i + n] = outtemp[i];
        }

        outstring = "";
        for (n = 0; n <= outlen - 1; n++)
        {
            outstring = outstring + outb[n].ToString("X2");
        }
        return outstring;
    }

    /// <summary>
    /// 使用增强算法，加密字符串
    /// </summary>
    /// <param name="InString"></param>
    /// <param name="Key"></param>
    /// <returns></returns>
    public string DecryptString(string InString, string Key)
    {
        byte[] b, outb;
        byte[] temp = new byte[8], outtemp = new byte[8];
        int n, i, nlen, outlen;
        string temp_string;
        StringBuilder c_str;


        nlen = InString.Length;
        if (nlen < 16) outlen = 16;
        outlen = nlen / 2;
        b = new byte[outlen];
        outb = new byte[outlen];

        i = 0;
        for (n = 1; n <= nlen; n = n + 2)
        {
            temp_string = InString.Substring(n - 1, 2);
            b[i] = System.Convert.ToByte(HexToInt(temp_string));
            i = i + 1;
        }

        b.CopyTo(outb, 0);

        for (n = 0; n <= outlen - 8; n = n + 8)
        {
            for (i = 0; i < 8; i++) temp[i] = b[i + n];
            DeCode(temp, outtemp, Key);
            for (i = 0; i < 8; i++) outb[i + n] = outtemp[i];
        }

        c_str = new StringBuilder("", outlen);
        CopyByteToString(c_str, outb, outlen);
        return c_str.ToString();

    }

    private bool isfindmydevice(int pos, ref int count, ref string OutPath)
    {
        return Subisfindmydevice(pos, ref count, ref OutPath);
    }

    private bool Subisfindmydevice(int pos, ref int count, ref string OutPath)
    {
        IntPtr hardwareDeviceInfo;
        SP_INTERFACE_DEVICE_DATA DeviceInfoData = new SP_INTERFACE_DEVICE_DATA();
        int i;
        GUID HidGuid = new GUID();
        SP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData = new SP_DEVICE_INTERFACE_DETAIL_DATA();
        int requiredLength;
        IntPtr d_handle;
        HIDD_ATTRIBUTES Attributes = new HIDD_ATTRIBUTES();

        i = 0; count = 0;
        HidD_GetHidGuid(ref HidGuid);

        hardwareDeviceInfo = SetupDiGetClassDevsA(ref HidGuid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

        if (hardwareDeviceInfo == (IntPtr)INVALID_HANDLE_VALUE) return false;

        DeviceInfoData.cbSize = Marshal.SizeOf(DeviceInfoData);

        while (SetupDiEnumDeviceInterfaces(hardwareDeviceInfo, 0, ref HidGuid, i, ref DeviceInfoData))
        {
            if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
            if (System.IntPtr.Size == 4)
                functionClassDeviceData.cbSize = 5;
            else
                functionClassDeviceData.cbSize = 8;
            requiredLength = 0;
            if (!SetupDiGetDeviceInterfaceDetailA(hardwareDeviceInfo, ref DeviceInfoData, ref functionClassDeviceData, 300, ref requiredLength, 0))
            {
                SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
                return false;
            }
            OutPath = ByteConvertString(functionClassDeviceData.DevicePath);
            d_handle = CreateFile(OutPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
            if ((IntPtr)INVALID_HANDLE_VALUE != d_handle)
            {
                if (HidD_GetAttributes(d_handle, ref Attributes))
                {
                    if ((Attributes.ProductID == PID) && (Attributes.VendorID == VID) ||
                        (Attributes.ProductID == PID_NEW) && (Attributes.VendorID == VID_NEW) ||
                        (Attributes.ProductID == PID_NEW_2) && (Attributes.VendorID == VID_NEW_2))
                    {
                        if (pos == count)
                        {
                            SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
                            CloseHandle(d_handle);
                            return true;
                        }
                        count = count + 1;
                    }
                }
                CloseHandle(d_handle);
            }
            i = i + 1;

        }
        SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
        return false;
    }

    private bool GetFeature(IntPtr hDevice, byte[] array_out, int out_len)
    {

        bool FeatureStatus;
        bool Status;
        int i;
        byte[] FeatureReportBuffer = new byte[512];
        IntPtr Ppd = System.IntPtr.Zero;
        HIDP_CAPS Caps = new HIDP_CAPS();

        if (!HidD_GetPreparsedData(hDevice, ref Ppd)) return false;

        if (HidP_GetCaps(Ppd, ref Caps) <= 0)
        {
            HidD_FreePreparsedData(Ppd);
            return false;
        }

        Status = true;

        FeatureReportBuffer[0] = 1;

        FeatureStatus = HidD_GetFeature(hDevice, FeatureReportBuffer, Caps.FeatureReportByteLength);
        if (FeatureStatus)
        {
            for (i = 0; i < out_len; i++)
            {
                array_out[i] = FeatureReportBuffer[i];
            }
        }


        Status = Status && FeatureStatus;
        HidD_FreePreparsedData(Ppd);

        return Status;

    }

    private bool SetFeature(IntPtr hDevice, byte[] array_in, int in_len)
    {
        bool FeatureStatus;
        bool Status;
        int i;
        byte[] FeatureReportBuffer = new byte[512];
        IntPtr Ppd = System.IntPtr.Zero;
        HIDP_CAPS Caps = new HIDP_CAPS();

        if (!HidD_GetPreparsedData(hDevice, ref Ppd)) return false;

        if (HidP_GetCaps(Ppd, ref Caps) <= 0)
        {
            HidD_FreePreparsedData(Ppd);
            return false;
        }

        Status = true;

        FeatureReportBuffer[0] = 2;

        for (i = 0; i < in_len; i++)
        {
            FeatureReportBuffer[i + 1] = array_in[i + 1];

        }
        FeatureStatus = HidD_SetFeature(hDevice, FeatureReportBuffer, Caps.FeatureReportByteLength);


        Status = Status && FeatureStatus;
        HidD_FreePreparsedData(Ppd);

        return Status;

    }

    private int NT_FindPort(int start, ref string OutPath)
    {
        int count = 0;
        if (!isfindmydevice(start, ref count, ref OutPath))
        {
            return -92;
        }
        return 0;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="hUsbDevice"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    private int OpenMydivece(ref IntPtr hUsbDevice, string Path)
    {
        string OutPath;
        bool biao;
        int count = 0;
        if (Path.Length < 1)
        {
            OutPath = "";
            biao = isfindmydevice(0, ref count, ref OutPath);
            if (!biao) return -92;
            hUsbDevice = CreateFile(OutPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
            if (hUsbDevice == (IntPtr)INVALID_HANDLE_VALUE) return -92;
        }
        else
        {
            hUsbDevice = CreateFile(Path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
            if (hUsbDevice == (IntPtr)INVALID_HANDLE_VALUE) return -92;
        }
        return 0;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="Version"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    private int GetIDVersion(ref short Version, string Path)
    {
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 1;
        if (!SetFeature(hUsbDevice, array_in, 1)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 1)) { CloseHandle(hUsbDevice); return -93; }
        CloseHandle(hUsbDevice);
        Version = array_out[0];
        return 0;
    }

    private int NT_GetID(ref int ID_1, ref int ID_2, string Path)
    {
        int[] t = new int[8];
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 2;
        if (!SetFeature(hUsbDevice, array_in, 1)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 8)) { CloseHandle(hUsbDevice); return -93; }
        CloseHandle(hUsbDevice);
        t[0] = array_out[0]; t[1] = array_out[1]; t[2] = array_out[2]; t[3] = array_out[3];
        t[4] = array_out[4]; t[5] = array_out[5]; t[6] = array_out[6]; t[7] = array_out[7];
        ID_1 = t[3] | (t[2] << 8) | (t[1] << 16) | (t[0] << 24);
        ID_2 = t[7] | (t[6] << 8) | (t[5] << 16) | (t[4] << 24);
        return 0;
    }

    private int Y_Read(byte[] OutData, int address, int nlen, byte[] password, string Path, int pos)
    {
        int addr_l;
        int addr_h;
        int n;
        byte[] array_in = new byte[512];
        byte[] array_out = new byte[512];
        if ((address > MAX_LEN) || (address < 0)) return -81;
        if ((nlen > 255)) return -87;
        if ((nlen + address) > MAX_LEN) return -88;
        addr_h = (address >> 8) * 2;
        addr_l = address & 255;
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;

        array_in[1] = 0x12;
        array_in[2] = (byte)addr_h;
        array_in[3] = (byte)addr_l;
        array_in[4] = (byte)nlen;
        for (n = 0; n <= 7; n++)
        {
            array_in[5 + n] = password[n];
        }
        if (!SetFeature(hUsbDevice, array_in, 13)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, nlen + 1)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0)
        {
            return -83;
        }
        for (n = 0; n < nlen; n++)
        {
            OutData[n + pos] = array_out[n + 1];
        }
        return 0;
    }

    private int Y_Write(byte[] indata, int address, int nlen, byte[] password, string Path, int pos)
    {
        int addr_l;
        int addr_h;
        int n;
        byte[] array_in = new byte[512];
        byte[] array_out = new byte[512];
        if ((nlen > 255)) return -87;
        if ((address + nlen - 1) > (MAX_LEN + 17) || (address < 0)) return -81;
        addr_h = (address >> 8) * 2;
        addr_l = address & 255;
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 0x13;
        array_in[2] = (byte)addr_h;
        array_in[3] = (byte)addr_l;
        array_in[4] = (byte)nlen;
        for (n = 0; n <= 7; n++)
        {
            array_in[5 + n] = password[n];
        }
        for (n = 0; n < nlen; n++)
        {
            array_in[13 + n] = indata[n + pos];
        }
        if (!SetFeature(hUsbDevice, array_in, 13 + nlen)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 2)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0)
        {
            return -82;
        }
        return 0;
    }

    private int NT_Cal(byte[] InBuf, byte[] outbuf, string Path, int pos)
    {
        int n;
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 8;
        for (n = 2; n <= 9; n++)
        {
            array_in[n] = InBuf[n - 2 + pos];
        }
        if (!SetFeature(hUsbDevice, array_in, 9)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 9)) { CloseHandle(hUsbDevice); return -93; }
        CloseHandle(hUsbDevice);
        for (n = 0; n < 8; n++)
        {
            outbuf[n + pos] = array_out[n];
        }
        if (array_out[8] != 0x55)
        {
            return -20;
        }
        return 0;
    }

    private int NT_SetCal_2(byte[] indata, byte IsHi, string Path, short pos)
    {

        int n;
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 9;
        array_in[2] = IsHi;
        for (n = 0; n < 8; n++)
        {
            array_in[3 + n] = indata[n + pos];
        }
        if (!SetFeature(hUsbDevice, array_in, 11)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 2)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0)
        {
            return -82;
        }

        return 0;
    }

    /// <summary>
    /// 获到锁的版本
    /// </summary>
    /// <param name="Version"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int NT_GetIDVersion(ref short Version, string Path)
    {
        int ret;
        IntPtr hsignal;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = GetIDVersion(ref Version, Path);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    public int GetID(ref int ID_1, ref int ID_2, string Path)
    {
        int ret;
        IntPtr hsignal;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_GetID(ref ID_1, ref ID_2, Path);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    public int YWriteEx(byte[] indata, int address, int nlen, string HKey, string LKey, string Path)
    {
        int ret = 0;
        IntPtr hsignal;
        byte[] password = new byte[8];
        int n, trashLen = 0;
        int leave;
        int temp_leave;
        if ((address + nlen - 1 > MAX_LEN) || (address < 0)) return -81;

        ret = GetTrashBufLen(Path, ref trashLen);
        if (trashLen < 100) trashLen = 16;
        trashLen = trashLen - 8;
        if (ret != 0) return ret;

        myconvert(HKey, LKey, password);
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        temp_leave = address % trashLen;
        leave = trashLen - temp_leave;
        if (leave > nlen) leave = nlen;
        if (leave > 0)
        {
            for (n = 0; n < leave / trashLen; n++)
            {
                ret = Y_Write(indata, address + n * trashLen, trashLen, password, Path, trashLen * n);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YWriteEx(indata, address, nlen, HKey, LKey, Path); }
            }
            if (leave - trashLen * n > 0)
            {
                ret = Y_Write(indata, address + n * trashLen, leave - n * trashLen, password, Path, trashLen * n);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YWriteEx(indata, address, nlen, HKey, LKey, Path); }
            }
        }
        nlen = nlen - leave; address = address + leave;
        if (nlen > 0)
        {

            for (n = 0; n < nlen / trashLen; n++)
            {
                ret = Y_Write(indata, address + n * trashLen, trashLen, password, Path, leave + trashLen * n);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YWriteEx(indata, address, nlen, HKey, LKey, Path); }
            }
            if (nlen - trashLen * n > 0)
            {
                ret = Y_Write(indata, address + n * trashLen, nlen - n * trashLen, password, Path, leave + trashLen * n);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YWriteEx(indata, address, nlen, HKey, LKey, Path); }
            }
        }
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    public int YReadEx(byte[] OutData, short address, short nlen, string HKey, string LKey, string Path)
    {
        int ret = 0;
        IntPtr hsignal;
        byte[] password = new byte[8];
        int n, trashLen = 0;

        if ((address + nlen - 1 > MAX_LEN) || (address < 0)) return (-81);

        ret = GetTrashBufLen(Path, ref trashLen);
        if (trashLen < 100) trashLen = 16;
        if (ret != 0) return ret;


        myconvert(HKey, LKey, password);
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        for (n = 0; n < nlen / trashLen; n++)
        {
            ret = Y_Read(OutData, address + n * trashLen, trashLen, password, Path, n * trashLen);
            if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YReadEx(OutData, address, nlen, HKey, LKey, Path); }
        }
        if (nlen - trashLen * n > 0)
        {
            ret = Y_Read(OutData, address + n * trashLen, nlen - trashLen * n, password, Path, trashLen * n);
            if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YReadEx(OutData, address, nlen, HKey, LKey, Path); }
        }
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 查找加密锁
    /// </summary>
    /// <param name="start"></param>
    /// <param name="OutPath"></param>
    /// <returns></returns>
    public int FindPort(int start, ref string OutPath)
    {
        int ret;
        IntPtr hsignal;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_FindPort(start, ref OutPath);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    private string AddZero(string InKey)
    {
        int nlen;
        int n;
        nlen = InKey.Length;
        for (n = nlen; n <= 7; n++)
        {
            InKey = "0" + InKey;
        }
        return InKey;
    }

    private void myconvert(string HKey, string LKey, byte[] out_data)
    {
        HKey = AddZero(HKey);
        LKey = AddZero(LKey);
        int n;
        for (n = 0; n <= 3; n++)
        {
            out_data[n] = (byte)HexToInt(HKey.Substring(n * 2, 2));
        }
        for (n = 0; n <= 3; n++)
        {
            out_data[n + 4] = (byte)HexToInt(LKey.Substring(n * 2, 2));
        }
    }
    public int YRead(ref byte indata, int address, string HKey, string LKey, string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] ary1 = new byte[8];

        if ((address > 495) || (address < 0)) return -81;
        myconvert(HKey, LKey, ary1);
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = sub_YRead(ref indata, address, ary1, Path);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }
    private int sub_YRead(ref byte OutData, int address, byte[] password, string Path)
    {
        int n;
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        byte opcode;
        if ((address > 495) || (address < 0)) return -81;
        opcode = 128;
        if (address > 255)
        {
            opcode = 160;
            address = address - 256;
        }

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 16;
        array_in[2] = opcode;
        array_in[3] = (byte)address;
        array_in[4] = (byte)address;
        for (n = 0; n < 8; n++)
        {
            array_in[5 + n] = password[n];
        }
        if (!SetFeature(hUsbDevice, array_in, 13))
        {
            CloseHandle(hUsbDevice); return -93;
        }
        if (!GetFeature(hUsbDevice, array_out, 2))
        {
            CloseHandle(hUsbDevice); return -94;
        }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 83)
        {
            return -83;
        }
        OutData = array_out[1];
        return 0;
    }

    public int YWrite(byte indata, int address, string HKey, string LKey, string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] ary1 = new byte[8];

        if ((address > 495) || (address < 0)) return -81;
        myconvert(HKey, LKey, ary1);
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = sub_YWrite(indata, address, ary1, Path);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }
    private int sub_YWrite(byte indata, int address, byte[] password, string Path)
    {
        int n;
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        byte opcode;
        if ((address > 511) || (address < 0)) return -81;
        opcode = 64;
        if (address > 255)
        {
            opcode = 96;
            address = address - 256;
        }

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 17;
        array_in[2] = opcode;
        array_in[3] = (byte)address;
        array_in[4] = indata;
        for (n = 0; n < 8; n++)
        {
            array_in[5 + n] = password[n];
        }
        if (!SetFeature(hUsbDevice, array_in, 13))
        {
            CloseHandle(hUsbDevice); return -93;
        }
        if (!GetFeature(hUsbDevice, array_out, 2))
        {
            CloseHandle(hUsbDevice); return -94;
        }
        CloseHandle(hUsbDevice);
        if (array_out[1] != 1)
        {
            return -82;
        }
        return 0;
    }

    /// <summary>
    /// 设置读密码
    /// </summary>
    /// <param name="W_HKey"></param>
    /// <param name="W_LKey"></param>
    /// <param name="new_HKey"></param>
    /// <param name="new_LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int SetReadPassword(string W_HKey, string W_LKey, string new_HKey, string new_LKey, string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] ary1 = new byte[8];
        byte[] ary2 = new byte[8];
        short address;
        myconvert(W_HKey, W_LKey, ary1);
        myconvert(new_HKey, new_LKey, ary2);
        address = 496;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = Y_Write(ary2, address, 8, ary1, Path, 0);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 设置写密码
    /// </summary>
    /// <param name="W_HKey"></param>
    /// <param name="W_LKey"></param>
    /// <param name="new_HKey"></param>
    /// <param name="new_LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int SetWritePassword(string W_HKey, string W_LKey, string new_HKey, string new_LKey, string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] ary1 = new byte[8];
        byte[] ary2 = new byte[8];
        short address;
        myconvert(W_HKey, W_LKey, ary1);
        myconvert(new_HKey, new_LKey, ary2);
        address = 504;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = Y_Write(ary2, address, 8, ary1, Path, 0);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 设置读密码 针对新Dog
    /// </summary>
    /// <param name="W_HKey"></param>
    /// <param name="W_LKey"></param>
    /// <param name="new_HKey"></param>
    /// <param name="new_LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int SetReadPasswordForNewDog(string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] ary1 = new byte[8];
        byte[] ary2 = new byte[8];
        short address;
        myconvert(WritePasswordH, WritePasswordL, ary1);
        myconvert(ReadPasswordH, ReadPasswordL, ary2);
        address = 496;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = Y_Write(ary2, address, 8, ary1, Path, 0);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 设置写密码  针对新Dog
    /// </summary>
    /// <param name="W_HKey"></param>
    /// <param name="W_LKey"></param>
    /// <param name="new_HKey"></param>
    /// <param name="new_LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int SetWritePasswordForNewDog(string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] ary1 = new byte[8];
        byte[] ary2 = new byte[8];
        short address;
        myconvert(OriginWritePasswordH, OriginWritePasswordL, ary1);
        myconvert(WritePasswordH, WritePasswordL, ary2);
        address = 504;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = Y_Write(ary2, address, 8, ary1, Path, 0);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 设置写密码  针对旧Dog
    /// </summary>
    /// <param name="W_HKey"></param>
    /// <param name="W_LKey"></param>
    /// <param name="new_HKey"></param>
    /// <param name="new_LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int SetWritePasswordForOldDog(string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] ary1 = new byte[8];
        byte[] ary2 = new byte[8];
        short address;
        myconvert(WritePasswordH, WritePasswordL, ary1);
        myconvert(OriginWritePasswordH, OriginWritePasswordL, ary2);
        address = 504;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = Y_Write(ary2, address, 8, ary1, Path, 0);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 设置读密码 针对旧Dog
    /// </summary>
    /// <param name="W_HKey"></param>
    /// <param name="W_LKey"></param>
    /// <param name="new_HKey"></param>
    /// <param name="new_LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int SetReadPasswordForOldDog(string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] ary1 = new byte[8];
        byte[] ary2 = new byte[8];
        short address;
        myconvert(ReadPasswordH, ReadPasswordL, ary1);
        myconvert(OriginReadPasswordH, OriginReadPasswordL, ary2);
        address = 496;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = Y_Write(ary2, address, 8, ary1, Path, 0);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }


    /// <summary>
    /// 写字符串
    /// </summary>
    /// <param name="InString"></param>
    /// <param name="address"></param>
    /// <param name="HKey"></param>
    /// <param name="LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int YWriteString(string InString, int address, string HKey, string LKey, string Path)
    {
        int ret = 0;
        byte[] ary1 = new byte[8];
        IntPtr hsignal;
        int n, trashLen = 0;
        int outlen;
        int total_len;
        int temp_leave;
        int leave;
        byte[] b;
        if ((address < 0)) return -81;

        ret = GetTrashBufLen(Path, ref trashLen);
        if (trashLen < 100) trashLen = 16;
        trashLen = trashLen - 8;
        if (ret != 0) return ret;

        myconvert(HKey, LKey, ary1);

        outlen = lstrlenA(InString); //注意，这里不写入结束字符串，与原来的兼容，也可以写入结束字符串，与原来的不兼容，写入长度会增加1
        b = new byte[outlen];
        CopyStringToByte(b, InString, outlen);

        total_len = address + outlen;
        if (total_len > MAX_LEN) return -47;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        temp_leave = address % trashLen;
        leave = trashLen - temp_leave;
        if (leave > outlen) leave = outlen;

        if (leave > 0)
        {
            for (n = 0; n < (leave / trashLen); n++)
            {
                ret = Y_Write(b, address + n * trashLen, trashLen, ary1, Path, n * trashLen);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YWrite_new((InString), address, HKey, LKey, Path); }
            }
            if (leave - trashLen * n > 0)
            {
                ret = Y_Write(b, address + n * trashLen, leave - n * trashLen, ary1, Path, trashLen * n);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YWrite_new((InString), address, HKey, LKey, Path); }
            }
        }
        outlen = outlen - leave;
        address = address + leave;
        if (outlen > 0)
        {
            for (n = 0; n < (outlen / trashLen); n++)
            {
                ret = Y_Write(b, address + n * trashLen, trashLen, ary1, Path, leave + n * trashLen);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return ret; }
            }
            if (outlen - trashLen * n > 0)
            {
                ret = Y_Write(b, address + n * trashLen, outlen - n * trashLen, ary1, Path, leave + trashLen * n);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return ret; }
            }
        }
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 读字符串
    /// </summary>
    /// <param name="OutString"></param>
    /// <param name="address"></param>
    /// <param name="nlen"></param>
    /// <param name="HKey"></param>
    /// <param name="LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int YReadString(ref string OutString, int address, int nlen, string HKey, string LKey, string Path)
    {
        int ret = 0;
        byte[] ary1 = new byte[8];
        IntPtr hsignal;
        int n, trashLen = 0;
        int total_len;
        byte[] outb;
        StringBuilder temp_OutString;
        outb = new byte[nlen];
        myconvert(HKey, LKey, ary1);
        if (address < 0) return -81;

        ret = GetTrashBufLen(Path, ref trashLen);
        if (trashLen < 100) trashLen = 16;
        if (ret != 0) return ret;

        total_len = address + nlen;
        if (total_len > MAX_LEN) return -47;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        for (n = 0; n < (nlen / trashLen); n++)
        {
            ret = Y_Read(outb, address + n * trashLen, trashLen, ary1, Path, n * trashLen);
            if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YRead_new(ref OutString, address, nlen, HKey, LKey, Path); }
        }
        if (nlen - trashLen * n > 0)
        {
            ret = Y_Read(outb, address + n * trashLen, nlen - trashLen * n, ary1, Path, trashLen * n);
            if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YRead_new(ref OutString, address, nlen, HKey, LKey, Path); }
        }
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        temp_OutString = new StringBuilder("", nlen);
        //初始化数据为0，注意，这步一定是需要的
        for (n = 0; n < nlen; n++)
        {
            temp_OutString.Append(0);
        }
        CopyByteToString(temp_OutString, outb, nlen);
        OutString = temp_OutString.ToString();
        return ret;
    }

    /// <summary>
    /// 写字符串
    /// </summary>
    /// <param name="InString"></param>
    /// <param name="address"></param>
    /// <param name="HKey"></param>
    /// <param name="LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int Write(string InString, int address, string Path)
    {
        int ret = 0;
        byte[] ary1 = new byte[8];
        IntPtr hsignal;
        int n, trashLen = 0;
        int outlen;
        int total_len;
        int temp_leave;
        int leave;
        byte[] b;
        if ((address < 0)) return -81;

        ret = GetTrashBufLen(Path, ref trashLen);
        if (trashLen < 100) trashLen = 16;
        trashLen = trashLen - 8;
        if (ret != 0) return ret;

        myconvert(WritePasswordH, WritePasswordL, ary1);

        outlen = lstrlenA(InString); //注意，这里不写入结束字符串，与原来的兼容，也可以写入结束字符串，与原来的不兼容，写入长度会增加1
        b = new byte[outlen];
        CopyStringToByte(b, InString, outlen);

        total_len = address + outlen;
        if (total_len > MAX_LEN) return -47;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        temp_leave = address % trashLen;
        leave = trashLen - temp_leave;
        if (leave > outlen) leave = outlen;

        if (leave > 0)
        {
            for (n = 0; n < (leave / trashLen); n++)
            {
                ret = Y_Write(b, address + n * trashLen, trashLen, ary1, Path, n * trashLen);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YWrite_new((InString), address, WritePasswordH, WritePasswordL, Path); }
            }
            if (leave - trashLen * n > 0)
            {
                ret = Y_Write(b, address + n * trashLen, leave - n * trashLen, ary1, Path, trashLen * n);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YWrite_new((InString), address, WritePasswordH, WritePasswordL, Path); }
            }
        }
        outlen = outlen - leave;
        address = address + leave;
        if (outlen > 0)
        {
            for (n = 0; n < (outlen / trashLen); n++)
            {
                ret = Y_Write(b, address + n * trashLen, trashLen, ary1, Path, leave + n * trashLen);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return ret; }
            }
            if (outlen - trashLen * n > 0)
            {
                ret = Y_Write(b, address + n * trashLen, outlen - n * trashLen, ary1, Path, leave + trashLen * n);
                if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return ret; }
            }
        }
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 读字符串
    /// </summary>
    /// <param name="OutString"></param>
    /// <param name="address"></param>
    /// <param name="nlen"></param>
    /// <param name="HKey"></param>
    /// <param name="LKey"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int Read(ref string OutString, int address, int nlen, string Path)
    {
        int ret = 0;
        byte[] ary1 = new byte[8];
        IntPtr hsignal;
        int n, trashLen = 0;
        int total_len;
        byte[] outb;
        StringBuilder temp_OutString;
        outb = new byte[nlen];
        myconvert(ReadPasswordH, ReadPasswordL, ary1);
        if (address < 0) return -81;

        ret = GetTrashBufLen(Path, ref trashLen);
        if (trashLen < 100) trashLen = 16;
        if (ret != 0) return ret;

        total_len = address + nlen;
        if (total_len > MAX_LEN) return -47;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        for (n = 0; n < (nlen / trashLen); n++)
        {
            ret = Y_Read(outb, address + n * trashLen, trashLen, ary1, Path, n * trashLen);
            if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YRead_new(ref OutString, address, nlen, ReadPasswordH, ReadPasswordL, Path); }
        }
        if (nlen - trashLen * n > 0)
        {
            ret = Y_Read(outb, address + n * trashLen, nlen - trashLen * n, ary1, Path, trashLen * n);
            if (ret != 0) { ReleaseSemaphore(hsignal, 1, 0); CloseHandle(hsignal); return sub_YRead_new(ref OutString, address, nlen, ReadPasswordH, ReadPasswordL, Path); }
        }
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        temp_OutString = new StringBuilder("", nlen);
        //初始化数据为0，注意，这步一定是需要的
        for (n = 0; n < nlen; n++)
        {
            temp_OutString.Append(0);
        }
        CopyByteToString(temp_OutString, outb, nlen);
        OutString = temp_OutString.ToString();
        return ret;
    }

    public int SetCal_2(string Key, string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] KeyBuf = new byte[16];
        byte[] inb = new byte[8];
        HexStringToByteArray(Key, ref KeyBuf);
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_SetCal_2(KeyBuf, 0, Path, 8);
        if (ret != 0) goto error1;
        ret = NT_SetCal_2(KeyBuf, 1, Path, 0);
    error1:
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 设置增强算法1 针对新
    /// </summary>
    /// <param name="Key"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int SetAdvancedAlgorithm(string Path)
    {
        int ret;
        IntPtr hsignal;
        byte[] KeyBuf = new byte[16];
        byte[] inb = new byte[8];
        HexStringToByteArray(AdvancedKey, ref KeyBuf);
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_SetCal_2(KeyBuf, 0, Path, 8);
        if (ret != 0) goto error1;
        ret = NT_SetCal_2(KeyBuf, 1, Path, 0);
    error1:
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    public int Cal(byte[] InBuf, byte[] outbuf, string Path)
    {
        int ret;
        IntPtr hsignal;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_Cal(InBuf, outbuf, Path, 0);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }

    /// <summary>
    /// 使用增强算法1加密字符串
    /// </summary>
    /// <param name="InString"></param>
    /// <param name="OutString"></param>
    /// <param name="Path"></param>
    /// <returns></returns>
    public int EncryptStringByAdvancedAlgorithm(string InString, ref string OutString, string Path)
    {
        IntPtr hsignal;
        byte[] b;
        byte[] outb;
        int n;
        int nlen, temp_len;
        int ret = 0;

        nlen = lstrlenA(InString) + 1;
        temp_len = nlen;
        if (nlen < 8)
        {
            nlen = 8;
        }


        b = new byte[nlen];
        outb = new byte[nlen];

        CopyStringToByte(b, InString, temp_len);

        b.CopyTo(outb, 0);

        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        for (n = 0; n <= (nlen - 8); n = n + 8)
        {
            ret = NT_Cal(b, outb, Path, n);
            if (ret != 0) break;
        }
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        OutString = "";
        for (n = 0; n < nlen; n++)
        {
            OutString = OutString + outb[n].ToString("X2");
        }
        return ret;

    }

    public int Reset(string Path)
    {
        int ret;
        IntPtr hsignal;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_ReSet(Path);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }
    private int NT_ReSet(string Path)
    {
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 32;
        if (!SetFeature(hUsbDevice, array_in, 2))
        {
            CloseHandle(hUsbDevice); return -93;
        }
        if (!GetFeature(hUsbDevice, array_out, 2))
        {
            CloseHandle(hUsbDevice); return -93;
        }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0)
        {
            return -82;
        }
        return 0;
    }



    public int NT_GetVersionEx(ref short Version, string Path)
    {
        int ret;
        IntPtr hsignal;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = F_GetVersionEx(ref Version, Path);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }


    private int F_GetVersionEx(ref short Version, string Path)
    {
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 5;
        if (!SetFeature(hUsbDevice, array_in, 1)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 1)) { CloseHandle(hUsbDevice); return -93; }
        CloseHandle(hUsbDevice);
        Version = array_out[0];
        return 0;
    }


    int sub_YRead_new(ref string OutString, int Address, int nlen, string HKey, string LKey, string Path)
    {
        int n, ret = 0;
        byte[] outb;
        StringBuilder temp_OutString;
        outb = new byte[nlen];
        for (n = 0; n < nlen; n++)
        {
            ret = YRead(ref outb[n], Address + n, HKey, LKey, Path);
            if (ret != 0) return ret;
        }
        temp_OutString = new StringBuilder("", nlen);
        //初始化数据为0，注意，这步一定是需要的
        for (n = 0; n < nlen; n++)
        {
            temp_OutString.Append(0);
        }
        CopyByteToString(temp_OutString, outb, nlen);
        OutString = temp_OutString.ToString();
        return ret;
    }

    int sub_YWrite_new(string InString, int Address, string HKey, string LKey, string Path)
    {
        int n, ret = 0;
        byte[] b;
        int outlen = lstrlenA(InString); //注意，这里不写入结束字符串，与原来的兼容，也可以写入结束字符串，与原来的不兼容，写入长度会增加1
        b = new byte[outlen];
        CopyStringToByte(b, InString, outlen);
        for (n = 0; n < outlen; n++)
        {
            ret = YWrite(b[n], Address + n, HKey, LKey, Path);
            if (ret != 0) return ret;
        }
        return ret;
    }

    int sub_YReadEx(byte[] OutData, int Address, int nlen, string HKey, string LKey, string Path)
    {
        int n, ret = 0;
        for (n = 0; n < nlen; n++)
        {
            ret = YRead(ref OutData[n], Address + n, HKey, LKey, Path);
            if (ret != 0) return ret;
        }
        return ret;
    }

    int sub_YWriteEx(byte[] indata, int Address, int len, string HKey, string LKey, string Path)
    {
        int n, ret = 0;
        for (n = 0; n < len; n++)
        {
            ret = YWrite(indata[n], Address + n, HKey, LKey, Path);
            if (ret != 0) return ret;
        }
        return ret;
    }

    public int SetHidOnly(bool IsHidOnly, string Path)
    {
        int ret;
        IntPtr hsignal;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_SetHidOnly(IsHidOnly, Path);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }
    private int NT_SetHidOnly(bool IsHidOnly, string Path)
    {
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 0x55;
        if (IsHidOnly) array_in[2] = 0; else array_in[2] = 0xff;
        if (!SetFeature(hUsbDevice, array_in, 3))
        {
            CloseHandle(hUsbDevice); return -93;
        }
        if (!GetFeature(hUsbDevice, array_out, 1))
        {
            CloseHandle(hUsbDevice); return -93;
        }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0)
        {
            return -82;
        }
        return 0;
    }

    public int SetUReadOnly(string Path)
    {
        int ret;
        IntPtr hsignal;
        hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_SetUReadOnly(Path);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }
    private int NT_SetUReadOnly(string Path)
    {
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 0x56;
        if (!SetFeature(hUsbDevice, array_in, 3))
        {
            CloseHandle(hUsbDevice); return -93;
        }
        if (!GetFeature(hUsbDevice, array_out, 1))
        {
            CloseHandle(hUsbDevice); return -93;
        }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0)
        {
            return -82;
        }
        return 0;
    }

    private int sub_GetTrashBufLen(IntPtr hDevice, ref int out_len)
    {

        IntPtr Ppd = System.IntPtr.Zero;
        HIDP_CAPS Caps = new HIDP_CAPS();

        if (!HidD_GetPreparsedData(hDevice, ref Ppd)) return -93;

        if (HidP_GetCaps(Ppd, ref Caps) <= 0)
        {
            HidD_FreePreparsedData(Ppd);
            return -93;
        }
        HidD_FreePreparsedData(Ppd);
        out_len = Caps.FeatureReportByteLength - 5;
        return 0;

    }
    private int GetTrashBufLen(string Path, ref int out_len)
    {

        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        int ret = sub_GetTrashBufLen(hUsbDevice, ref out_len);
        CloseHandle(hUsbDevice);
        return ret;

    }
    private int NT_Set_SM2_KeyPair(byte[] PriKey, byte[] PubKeyX, byte[] PubKeyY, byte[] sm2_UerName, string Path)
    {

        byte[] array_in = new byte[256];
        byte[] array_out = new byte[25];
        int n = 0; IntPtr hUsbDevice = IntPtr.Zero;

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 0x32;
        for (n = 0; n < ECC_MAXLEN; n++)
        {
            array_in[2 + n + ECC_MAXLEN * 0] = PriKey[n];
            array_in[2 + n + ECC_MAXLEN * 1] = PubKeyX[n];
            array_in[2 + n + ECC_MAXLEN * 2] = PubKeyY[n];
        }
        for (n = 0; n < SM2_USENAME_LEN; n++)
        {
            array_in[2 + n + ECC_MAXLEN * 3] = sm2_UerName[n];
        }

        if (!SetFeature(hUsbDevice, array_in, ECC_MAXLEN * 3 + SM2_USENAME_LEN + 2)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 2)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0x20) return USBStatusFail;

        return 0;
    }
    private int NT_GenKeyPair(byte[] PriKey, byte[] PubKey, string Path)
    {

        byte[] array_in = new byte[256];
        byte[] array_out = new byte[256];
        int n = 0; IntPtr hUsbDevice = IntPtr.Zero;
        array_out[0] = 0xfb;

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = GEN_KEYPAIR;
        if (!SetFeature(hUsbDevice, array_in, 2)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, ECC_MAXLEN * 3 + 2)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0x20)
        {

            return FAILEDGENKEYPAIR;//表示读取失败；

        }
        for (n = 0; n < ECC_MAXLEN; n++)
        {
            PriKey[n] = array_out[1 + ECC_MAXLEN * 0 + n];
        }
        for (n = 0; n < (ECC_MAXLEN * 2 + 1); n++)
        {
            PubKey[n] = array_out[1 + ECC_MAXLEN * 1 + n];
        }
        return 0;
    }

    private int NT_GetChipID(byte[] OutChipID, string Path)
    {
        int[] t = new int[8]; int n;
        byte[] array_in = new byte[25];
        byte[] array_out = new byte[25];
        IntPtr hUsbDevice = IntPtr.Zero;
        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = GET_CHIPID;
        if (!SetFeature(hUsbDevice, array_in, 1)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 17)) { CloseHandle(hUsbDevice); return -93; }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0x20) return USBStatusFail;
        for (n = 0; n < 16; n++)
        {
            OutChipID[n] = array_out[1 + n];
        }

        return 0;
    }


    private int NT_Get_SM2_PubKey(byte[] KGx, byte[] KGy, byte[] sm2_UerName, string Path)
    {

        byte[] array_in = new byte[256];
        byte[] array_out = new byte[256];
        int n = 0; IntPtr hUsbDevice = IntPtr.Zero;

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = 0x33;
        if (!SetFeature(hUsbDevice, array_in, 2)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, ECC_MAXLEN * 2 + SM2_USENAME_LEN + 2)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0x20) return USBStatusFail;

        for (n = 0; n < ECC_MAXLEN; n++)
        {
            KGx[n] = array_out[1 + ECC_MAXLEN * 0 + n];
            KGy[n] = array_out[1 + ECC_MAXLEN * 1 + n];
        }
        for (n = 0; n < SM2_USENAME_LEN; n++)
        {
            sm2_UerName[n] = array_out[1 + ECC_MAXLEN * 2 + n];
        }

        return 0;
    }

    private int NT_Set_Pin(string old_pin, string new_pin, string Path)
    {

        byte[] array_in = new byte[256];
        byte[] array_out = new byte[256];
        int n = 0; IntPtr hUsbDevice = IntPtr.Zero;

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = SET_PIN;
        byte[] b_oldpin = new byte[PIN_LEN];
        CopyStringToByte(b_oldpin, old_pin, PIN_LEN);
        byte[] b_newpin = new byte[PIN_LEN];
        CopyStringToByte(b_newpin, new_pin, PIN_LEN);
        for (n = 0; n < PIN_LEN; n++)
        {
            array_in[2 + PIN_LEN * 0 + n] = b_oldpin[n];
            array_in[2 + PIN_LEN * 1 + n] = b_newpin[n];
        }

        if (!SetFeature(hUsbDevice, array_in, PIN_LEN * 2 + 2)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 2)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0x20) return USBStatusFail;
        if (array_out[1] != 0x20) return FAILPINPWD;
        return 0;
    }


    private int NT_SM2_Enc(byte[] inbuf, byte[] outbuf, byte inlen, string Path)
    {

        byte[] array_in = new byte[256];
        byte[] array_out = new byte[256];
        int n = 0; IntPtr hUsbDevice = IntPtr.Zero;

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = MYENC;
        array_in[2] = inlen;
        for (n = 0; n < inlen; n++)
        {
            array_in[3 + n] = inbuf[n];
        }
        if (!SetFeature(hUsbDevice, array_in, inlen + 1 + 2)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, inlen + SM2_ADDBYTE + 3)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[0] != 0x20) return USBStatusFail;
        if (array_out[1] == 0) return FAILENC;

        for (n = 0; n < (inlen + SM2_ADDBYTE); n++)
        {
            outbuf[n] = array_out[2 + n];
        }

        return 0;
    }

    private int NT_SM2_Dec(byte[] inbuf, byte[] outbuf, byte inlen, string pin, string Path)
    {

        byte[] array_in = new byte[256];
        byte[] array_out = new byte[256];
        int n = 0; IntPtr hUsbDevice = IntPtr.Zero;

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = MYDEC;
        byte[] b_pin = new byte[PIN_LEN];
        CopyStringToByte(b_pin, pin, PIN_LEN);
        for (n = 0; n < PIN_LEN; n++)
        {
            array_in[2 + PIN_LEN * 0 + n] = b_pin[n];
        }
        array_in[2 + PIN_LEN] = inlen;
        for (n = 0; n < inlen; n++)
        {
            array_in[2 + PIN_LEN + 1 + n] = inbuf[n];
        }
        if (!SetFeature(hUsbDevice, array_in, inlen + 1 + 2 + PIN_LEN)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, inlen - SM2_ADDBYTE + 4)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[2] != 0x20) return FAILPINPWD;
        if (array_out[1] == 0) return FAILENC;
        if (array_out[0] != 0x20) return USBStatusFail;
        for (n = 0; n < (inlen - SM2_ADDBYTE); n++)
        {
            outbuf[n] = array_out[3 + n];
        }

        return 0;
    }

    private int NT_Sign(byte[] inbuf, byte[] outbuf, string pin, string Path)
    {

        byte[] array_in = new byte[256];
        byte[] array_out = new byte[256];
        int n = 0; IntPtr hUsbDevice = IntPtr.Zero;

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = YTSIGN;
        byte[] b_pin = new byte[PIN_LEN];
        CopyStringToByte(b_pin, pin, PIN_LEN);
        for (n = 0; n < PIN_LEN; n++)
        {
            array_in[2 + PIN_LEN * 0 + n] = b_pin[n];
        }
        for (n = 0; n < 32; n++)
        {
            array_in[2 + PIN_LEN + n] = inbuf[n];
        }
        if (!SetFeature(hUsbDevice, array_in, 32 + 2 + PIN_LEN)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 64 + 3)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[1] != 0x20) return FAILPINPWD;
        if (array_out[0] != 0x20) return USBStatusFail;
        for (n = 0; n < 64; n++)
        {
            outbuf[n] = array_out[2 + n];
        }

        return 0;
    }

    private int NT_Sign_2(byte[] inbuf, byte[] outbuf, string pin, string Path)
    {

        byte[] array_in = new byte[256];
        byte[] array_out = new byte[256];
        int n = 0; IntPtr hUsbDevice = IntPtr.Zero;

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = YTSIGN_2;
        byte[] b_pin = new byte[PIN_LEN];
        CopyStringToByte(b_pin, pin, PIN_LEN);
        for (n = 0; n < PIN_LEN; n++)
        {
            array_in[2 + PIN_LEN * 0 + n] = b_pin[n];
        }
        for (n = 0; n < 32; n++)
        {
            array_in[2 + PIN_LEN + n] = inbuf[n];
        }
        if (!SetFeature(hUsbDevice, array_in, 32 + 2 + PIN_LEN)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 64 + 3)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        if (array_out[1] != 0x20) return FAILPINPWD;
        if (array_out[0] != 0x20) return USBStatusFail;
        for (n = 0; n < 64; n++)
        {
            outbuf[n] = array_out[2 + n];
        }

        return 0;
    }


    private int NT_Verfiy(byte[] inbuf, byte[] InSignBuf, ref bool outbiao, string Path)
    {

        byte[] array_in = new byte[256];
        byte[] array_out = new byte[256];
        int n = 0; IntPtr hUsbDevice = IntPtr.Zero;

        if (OpenMydivece(ref hUsbDevice, Path) != 0) return -92;
        array_in[1] = YTVERIFY;
        for (n = 0; n < 32; n++)
        {
            array_in[2 + n] = inbuf[n];
        }
        for (n = 0; n < 64; n++)
        {
            array_in[2 + 32 + n] = InSignBuf[n];
        }
        if (!SetFeature(hUsbDevice, array_in, 32 + 2 + 64)) { CloseHandle(hUsbDevice); return -93; }
        if (!GetFeature(hUsbDevice, array_out, 3)) { CloseHandle(hUsbDevice); return -94; }
        CloseHandle(hUsbDevice);
        outbiao = (array_out[1] != 0);
        if (array_out[0] != 0x20) return USBStatusFail;

        return 0;
    }
    private string ByteArrayToHexString(byte[] in_data, int nlen)
    {
        string OutString = ""; int n;
        for (n = 0; n < nlen; n++)
        {
            OutString = OutString + in_data[n].ToString("X2");
        }
        return OutString;
    }

    public int YT_GenKeyPair(ref string PriKey, ref string PubKeyX, ref string PubKeyY, string InPath)
    {

        int ret, n; byte[] b_PriKey = new byte[ECC_MAXLEN], b_PubKey = new byte[ECC_MAXLEN * 2 + 1];//其中第一个字节是标志位，忽略
        IntPtr hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_GenKeyPair(b_PriKey, b_PubKey, InPath);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        PriKey = ByteArrayToHexString(b_PriKey, ECC_MAXLEN);
        PubKeyX = ""; PubKeyY = "";
        for (n = 0; n < ECC_MAXLEN; n++)
        {
            PubKeyX = PubKeyX + b_PubKey[n + 1].ToString("X2");
            PubKeyY = PubKeyY + b_PubKey[n + 1 + ECC_MAXLEN].ToString("X2");

        }
        return ret;

    }

    public int Set_SM2_KeyPair(string PriKey, string PubKeyX, string PubKeyY, string SM2_UserName, string InPath)
    {

        int ret; byte[] b_PriKey = new byte[ECC_MAXLEN], b_PubKeyX = new byte[ECC_MAXLEN], b_PubKeyY = new byte[ECC_MAXLEN], b_SM2UserName = new byte[SM2_USENAME_LEN];
        HexStringToByteArray(PriKey, ref b_PriKey);
        HexStringToByteArray(PubKeyX, ref b_PubKeyX);
        HexStringToByteArray(PubKeyY, ref b_PubKeyY);
        CopyStringToByte(b_SM2UserName, SM2_UserName, SM2_USENAME_LEN);
        IntPtr hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_Set_SM2_KeyPair(b_PriKey, b_PubKeyX, b_PubKeyY, b_SM2UserName, InPath);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);

        return ret;

    }

    public int Get_SM2_PubKey(ref string PubKeyX, ref string PubKeyY, ref string sm2UserName, string InPath)
    {

        int ret; byte[] b_PubKeyX = new byte[ECC_MAXLEN], b_PubKeyY = new byte[ECC_MAXLEN], b_sm2UserName = new byte[SM2_USENAME_LEN];
        IntPtr hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_Get_SM2_PubKey(b_PubKeyX, b_PubKeyY, b_sm2UserName, InPath);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        PubKeyX = ByteArrayToHexString(b_PubKeyX, ECC_MAXLEN);
        PubKeyY = ByteArrayToHexString(b_PubKeyY, ECC_MAXLEN);
        StringBuilder c_str = new StringBuilder("", SM2_USENAME_LEN);
        CopyByteToString(c_str, b_sm2UserName, SM2_USENAME_LEN);
        sm2UserName = c_str.ToString();
        return ret;

    }

    public int GetChipID(ref string OutChipID, string InPath)
    {

        int ret; byte[] b_OutChipID = new byte[16];
        IntPtr hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_GetChipID(b_OutChipID, InPath);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        OutChipID = ByteArrayToHexString(b_OutChipID, 16);
        return ret;

    }

    public int SM2_EncBuf(byte[] InBuf, byte[] OutBuf, int inlen, string InPath)
    {

        int ret = 0, n, temp_inlen, incount = 0, outcount = 0; byte[] temp_InBuf = new byte[MAX_ENCLEN + SM2_ADDBYTE], temp_OutBuf = new byte[MAX_ENCLEN + SM2_ADDBYTE];
        IntPtr hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        while (inlen > 0)
        {
            if (inlen > MAX_ENCLEN)
                temp_inlen = MAX_ENCLEN;
            else
                temp_inlen = inlen;
            for (n = 0; n < temp_inlen; n++)
            {
                temp_InBuf[n] = InBuf[incount + n];
            }
            ret = NT_SM2_Enc(temp_InBuf, temp_OutBuf, (byte)temp_inlen, InPath);
            for (n = 0; n < (temp_inlen + SM2_ADDBYTE); n++)
            {
                OutBuf[outcount + n] = temp_OutBuf[n];
            }
            if (ret != 0) goto err;
            inlen = inlen - MAX_ENCLEN;
            incount = incount + MAX_ENCLEN;
            outcount = outcount + MAX_DECLEN;
        }
    err:
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;

    }

    public int SM2_DecBuf(byte[] InBuf, byte[] OutBuf, int inlen, string pin, string InPath)
    {

        int ret = 0, temp_inlen, n, incount = 0, outcount = 0; byte[] temp_InBuf = new byte[MAX_ENCLEN + SM2_ADDBYTE], temp_OutBuf = new byte[MAX_ENCLEN + SM2_ADDBYTE];
        IntPtr hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        while (inlen > 0)
        {
            if (inlen > MAX_DECLEN)
                temp_inlen = MAX_DECLEN;
            else
                temp_inlen = inlen;
            for (n = 0; n < temp_inlen; n++)
            {
                temp_InBuf[n] = InBuf[incount + n];
            }
            ret = NT_SM2_Dec(InBuf, temp_OutBuf, (byte)temp_inlen, pin, InPath);
            for (n = 0; n < (temp_inlen - SM2_ADDBYTE); n++)
            {
                OutBuf[outcount + n] = temp_OutBuf[n];
            }
            if (ret != 0) goto err;
            inlen = inlen - MAX_DECLEN;
            incount = incount + MAX_DECLEN;
            outcount = outcount + MAX_ENCLEN;
        }
    err:
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;

    }

    public int SM2_EncString(string InString, ref string OutString, string InPath)
    {
        int n, incount = 0, outcount = 0; byte[] temp_InBuf = new byte[MAX_ENCLEN + SM2_ADDBYTE], temp_OutBuf = new byte[MAX_ENCLEN + SM2_ADDBYTE];
        int inlen = lstrlenA(InString) + 1;
        int outlen = (inlen / (MAX_ENCLEN) + 1) * SM2_ADDBYTE + inlen;
        byte[] OutBuf = new byte[outlen];
        byte[] InBuf = new byte[inlen];
        CopyStringToByte(InBuf, InString, inlen);
        int ret = 0, temp_inlen;
        IntPtr hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        while (inlen > 0)
        {
            if (inlen > MAX_ENCLEN)
                temp_inlen = MAX_ENCLEN;
            else
                temp_inlen = inlen;
            for (n = 0; n < temp_inlen; n++)
            {
                temp_InBuf[n] = InBuf[incount + n];
            }
            ret = NT_SM2_Enc(temp_InBuf, temp_OutBuf, (byte)temp_inlen, InPath);
            for (n = 0; n < (temp_inlen + SM2_ADDBYTE); n++)
            {
                OutBuf[outcount + n] = temp_OutBuf[n];
            }
            if (ret != 0) goto err;
            inlen = inlen - MAX_ENCLEN;
            incount = incount + MAX_ENCLEN;
            outcount = outcount + MAX_DECLEN;
        }
    err:
        OutString = ByteArrayToHexString(OutBuf, outlen);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;

    }

    public int SM2_DecString(string InString, ref string OutString, string pin, string InPath)
    {
        int n, incount = 0, outcount = 0; byte[] temp_InBuf = new byte[MAX_ENCLEN + SM2_ADDBYTE], temp_OutBuf = new byte[MAX_ENCLEN + SM2_ADDBYTE];
        int inlen = lstrlenA(InString) / 2;
        int outlen = inlen - (inlen / (MAX_DECLEN) + 1) * SM2_ADDBYTE;
        byte[] InBuf = new byte[inlen];
        byte[] OutBuf = new byte[outlen];
        int ret = 0, temp_inlen;
        HexStringToByteArray(InString, ref InBuf);
        IntPtr hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        while (inlen > 0)
        {
            if (inlen > MAX_DECLEN)
                temp_inlen = MAX_DECLEN;
            else
                temp_inlen = inlen;
            for (n = 0; n < temp_inlen; n++)
            {
                temp_InBuf[n] = InBuf[incount + n];
            }
            ret = NT_SM2_Dec(temp_InBuf, temp_OutBuf, (byte)temp_inlen, pin, InPath);
            for (n = 0; n < (temp_inlen - SM2_ADDBYTE); n++)
            {
                OutBuf[outcount + n] = temp_OutBuf[n];
            }
            if (ret != 0) goto err;
            inlen = inlen - MAX_DECLEN;
            incount = incount + MAX_DECLEN;
            outcount = outcount + MAX_ENCLEN;
        }
    err:
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        StringBuilder c_str = new StringBuilder("", outlen);
        CopyByteToString(c_str, OutBuf, outlen);
        OutString = c_str.ToString();
        return ret;

    }



    public int YtSetPin(string old_pin, string new_pin, string InPath)
    {
        int ret;
        IntPtr hsignal = CreateSemaphore(0, 1, 1, "ex_sim");
        WaitForSingleObject(hsignal, INFINITE);
        ret = NT_Set_Pin(old_pin, new_pin, InPath);
        ReleaseSemaphore(hsignal, 1, 0);
        CloseHandle(hsignal);
        return ret;
    }


}

public struct GUID
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public byte[] Data1;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
    public byte[] Data2;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
    public byte[] Data3;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] Data4;
}

public struct SP_INTERFACE_DEVICE_DATA
{
    public int cbSize;
    public GUID InterfaceClassGuid;
    public int Flags;
    public IntPtr Reserved;
}



public struct SP_DEVINFO_DATA
{
    public int cbSize;
    public GUID ClassGuid;
    public int DevInst;
    public IntPtr Reserved;
}


public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
    public int cbSize;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
    public byte[] DevicePath;
}


public struct HIDD_ATTRIBUTES
{
    public int Size;
    public ushort VendorID;
    public ushort ProductID;
    public ushort VersionNumber;
}

public struct HIDP_CAPS
{
    public short Usage;
    public short UsagePage;
    public short InputReportByteLength;
    public short OutputReportByteLength;
    public short FeatureReportByteLength;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public short[] Reserved;
    public short NumberLinkCollectionNodes;
    public short NumberInputButtonCaps;
    public short NumberInputValueCaps;
    public short NumberInputDataIndices;
    public short NumberOutputButtonCaps;
    public short NumberOutputValueCaps;
    public short NumberOutputDataIndices;
    public short NumberFeatureButtonCaps;
    public short NumberFeatureValueCaps;
    public short NumberFeatureDataIndices;
}

/// <summary>
/// Defines the <see cref="Win32" />.
/// </summary>
public class Win32
{
    /// <summary>
    /// Defines the WM_DEVICECHANGE.
    /// </summary>
    public const int WM_DEVICECHANGE = 0x0219;

    /// <summary>
    /// Defines the DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE.
    /// </summary>
    public const int DBT_DEVICEARRIVAL = 0x8000, // systemdetected a new device
                       DBT_DEVICEREMOVECOMPLETE = 0x8004;// device is gone

    /// <summary>
    /// Defines the DEVICE_NOTIFY_WINDOW_HANDLE, DEVICE_NOTIFY_SERVICE_HANDLE.
    /// </summary>
    public const int DEVICE_NOTIFY_WINDOW_HANDLE = 0,
        DEVICE_NOTIFY_SERVICE_HANDLE = 1;

    /// <summary>
    /// Defines the DBT_DEVTYP_DEVICEINTERFACE.
    /// </summary>
    public const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005;// deviceinterface class

    /// <summary>
    /// Defines the GUID_DEVINTERFACE_USB_DEVICE.
    /// </summary>
    public static Guid GUID_DEVINTERFACE_USB_DEVICE = new
        Guid("4D1E55B2-F16F-11CF-88CB-001111000030");

    /// <summary>
    /// Defines the <see cref="DEV_BROADCAST_HDR" />.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public class DEV_BROADCAST_HDR
    {
        /// <summary>
        /// Defines the dbcc_size.
        /// </summary>
        public int dbcc_size;

        /// <summary>
        /// Defines the dbcc_devicetype.
        /// </summary>
        public int dbcc_devicetype;

        /// <summary>
        /// Defines the dbcc_reserved.
        /// </summary>
        public int dbcc_reserved;
    }

    /// <summary>
    /// Defines the <see cref="DEV_BROADCAST_DEVICEINTERFACE" />.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public class
        DEV_BROADCAST_DEVICEINTERFACE
    {
        /// <summary>
        /// Defines the dbcc_size.
        /// </summary>
        public int dbcc_size;

        /// <summary>
        /// Defines the dbcc_devicetype.
        /// </summary>
        public int dbcc_devicetype;

        /// <summary>
        /// Defines the dbcc_reserved.
        /// </summary>
        public int dbcc_reserved;

        /// <summary>
        /// Defines the dbcc_classguid.
        /// </summary>
        public Guid dbcc_classguid;

        /// <summary>
        /// Defines the dbcc_name.
        /// </summary>
        public short dbcc_name;
    }

    /// <summary>
    /// Defines the <see cref="DEV_BROADCAST_DEVICEINTERFACE1" />.
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public class DEV_BROADCAST_DEVICEINTERFACE1
    {
        /// <summary>
        /// Defines the dbcc_size.
        /// </summary>
        public int dbcc_size;

        /// <summary>
        /// Defines the dbcc_devicetype.
        /// </summary>
        public int dbcc_devicetype;

        /// <summary>
        /// Defines the dbcc_reserved.
        /// </summary>
        public int dbcc_reserved;

        /// <summary>
        /// Defines the dbcc_classguid.
        /// </summary>
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1,
            SizeConst = 16)]
        public byte[] dbcc_classguid;

        /// <summary>
        /// Defines the dbcc_name.
        /// </summary>
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
        public char[]
            dbcc_name;
    }

    /// <summary>
    /// The RegisterDeviceNotification.
    /// </summary>
    /// <param name="hRecipient">The hRecipient<see cref="IntPtr"/>.</param>
    /// <param name="NotificationFilter">The NotificationFilter<see cref="IntPtr"/>.</param>
    /// <param name="Flags">The Flags<see cref="Int32"/>.</param>
    /// <returns>The <see cref="IntPtr"/>.</returns>
    [DllImport("user32.dll", SetLastError = true)]
    public static extern
        IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr
        NotificationFilter, Int32 Flags);

    /// <summary>
    /// The GetLastError.
    /// </summary>
    /// <returns>The <see cref="int"/>.</returns>
    [DllImport("kernel32.dll")] public static extern int GetLastError();
}

